package com.faxsun.service.handlers;

import com.faxsun.core.order.domain.FSOrderItemImpl;
import com.faxsun.core.order.service.type.FSOrderStatus;
import com.faxsun.profile.core.domain.FSReferralStatusEnum;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.broadleafcommerce.common.email.service.EmailService;
import org.broadleafcommerce.common.email.service.info.EmailInfo;
import org.broadleafcommerce.common.exception.ServiceException;
import org.broadleafcommerce.core.order.dao.OrderDao;
import org.broadleafcommerce.core.order.domain.Order;
import org.broadleafcommerce.core.order.domain.OrderItem;
import org.broadleafcommerce.core.order.service.type.OrderStatus;
import org.broadleafcommerce.openadmin.dto.Entity;
import org.broadleafcommerce.openadmin.dto.PersistencePackage;
import org.broadleafcommerce.openadmin.dto.Property;
import org.broadleafcommerce.openadmin.server.service.persistence.PersistenceManager;
import org.broadleafcommerce.openadmin.server.service.persistence.PersistenceManagerEventHandlerAdapter;
import org.broadleafcommerce.openadmin.server.service.persistence.PersistenceManagerEventHandlerResponse;

import javax.annotation.Resource;
import java.util.HashMap;

/**
 * Order更新hook，可以CARD执行前后进行的操作
 *
 * @author zhaoteng.song@faxsun.com
 */
public class UpdateOrderHandler extends PersistenceManagerEventHandlerAdapter {

    private static final Log LOG = LogFactory.getLog(UpdateOrderHandler.class);

    private Order order = null;
    private OrderStatus oldStatus = null;

    @Resource(name = "blEmailService")
    protected EmailService emailService;

    @Resource(name = "blOrderConfirmedEmailInfo")
    protected EmailInfo orderConfirmedEmailInfo;

    @Resource(name = "blOrderDiliveriedEmailInfo")
    protected EmailInfo orderDiliveriedEmailInfo;

    @Resource(name = "blOrderDao")
    private OrderDao orderDao;

    @Override
    public int getOrder() {
        return HIGHEST_PRECEDENCE;
    }

    @Override
    public PersistenceManagerEventHandlerResponse preUpdate(
        PersistenceManager persistenceManager,
        PersistencePackage persistencePackage) throws ServiceException {

        Entity entity = persistencePackage.getEntity();

        boolean isOrder = isOrder(entity);

        if (isOrder) {

            Long id = Long.parseLong(getFieldFromProperties(entity, "id"));
            this.order = orderDao.readOrderById(id);
            oldStatus = this.order.getStatus();
            // FSOrderImpl fsOrder = (FSOrderImpl) order;
            // // 当订单状态或内部状态变为已签收时，级联修改订单状态
            // if (fsOrder.getStatus().equals(FSOrderStatus.SINGED)
            // || fsOrder.getInternalStatus().equals(
            // FSInternalOrderStatus.SINGED)) {
            // fsOrder.setInternalStatus(FSInternalOrderStatus.SINGED
            // .getType());
            // fsOrder.setStatus(FSOrderStatus.SINGED);
            // }

            return new PersistenceManagerEventHandlerResponse()
                .withStatus(PersistenceManagerEventHandlerResponse.PersistenceManagerEventHandlerResponseStatus.HANDLED);
        }

        return new PersistenceManagerEventHandlerResponse()
            .withStatus(PersistenceManagerEventHandlerResponse.PersistenceManagerEventHandlerResponseStatus.NOT_HANDLED);

    }

    private String getFieldFromProperties(Entity entity, String name) {

        Property p = entity.getPMap().get(name);
        return p.getValue();
    }

    private boolean isOrder(Entity entity) {
        @SuppressWarnings("rawtypes")
        Class clazz = null;
        boolean isOrder = true;
        try {
            clazz = Class.forName(entity.getType()[0]);
        } catch (Exception e) {
            e.printStackTrace();
            isOrder = false;
        }

        isOrder = isOrder && clazz != null
            && Order.class.isAssignableFrom(clazz);

        return isOrder;
    }

    @Override
    public PersistenceManagerEventHandlerResponse postUpdate(
        PersistenceManager persistenceManager, Entity entity,
        PersistencePackage persistencePackage) throws ServiceException {

        boolean isOrder = isOrder(entity);
        if (isOrder) {
            String curStatusString = getFieldFromProperties(entity, "status");
            OrderStatus oldStatus = this.oldStatus;
            OrderStatus curStatus = FSOrderStatus.getInstance(curStatusString);
            /*
             * if (order != null && (oldStatus.equals(FSOrderStatus.SUBMITTED)
			 * && curStatus .equals(FSOrderStatus.CONFIRMED))) {
			 * sendEmail(order, this.orderConfirmedEmailInfo); } else
			 */
            if (order != null && oldStatus != null && curStatus != null) {
                if (oldStatus.equals(FSOrderStatus.CONFIRMED) && curStatus.equals(FSOrderStatus.DELIVERY)) {
                    // 订单从已提交到已发货（客户视角）
                    sendEmail(order, this.orderDiliveriedEmailInfo);
                }

                if (oldStatus.equals(FSOrderStatus.DELIVERY) && curStatus.equals(FSOrderStatus.SINGED)) {
                    // 用户已收货（最好已过退货时间再操作）
                    updateReferralStatus(order);
                }
            }
        }
        return new PersistenceManagerEventHandlerResponse()
            .withStatus(PersistenceManagerEventHandlerResponse.PersistenceManagerEventHandlerResponseStatus.NOT_HANDLED);
    }

    protected void updateReferralStatus(Order order) {
        boolean statusChanged = false;
        for (OrderItem orderItem : order.getOrderItems()) {
            if (orderItem instanceof FSOrderItemImpl) {
                FSOrderItemImpl fsOrderItem = (FSOrderItemImpl) orderItem;
                if (fsOrderItem.getReferralCustomerOrderItemXref() != null) {
                    fsOrderItem.getReferralCustomerOrderItemXref().setReferralStatus(FSReferralStatusEnum.CONFIRMED);
                    if (!statusChanged) {
                        statusChanged = true;
                    }
                }
            }
        }
//        if(statusChanged){
//            orderDao.save(order);
//        }
    }

    protected void sendEmail(Order order, EmailInfo emailInfo) {
        HashMap<String, Object> vars = new HashMap<String, Object>();
        vars.put("customer", order.getCustomer());
        vars.put("orderNumber", order.getOrderNumber());
        vars.put("order", order);

        // Email service failing should not trigger rollback
        try {
            emailService.sendTemplateEmail(order.getEmailAddress(), emailInfo,
                vars);
        } catch (Exception e) {
            LOG.error(e);
        }
    }

}
